package cn.jx.cjm.security.common.config;

import cn.jx.cjm.security.common.filter.JwtAuthenticationTokenFilter;
import cn.jx.cjm.security.common.handler.*;
import cn.jx.cjm.security.support.SysUserSelfSupportService;
import cn.jx.cjm.common.util.JwtTokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;

/**
 * springSecurity配置中心
 *
 * @author 陈加敏
 * @since 2019/7/15 13:43
 */
@Configuration
public class CjmWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Autowired
    private LogoutSuccessHandlerImpl logoutSuccessHandler;
    @Autowired
    private AccessDeniedHandlerImpl accessDeniedHandler;
    @Autowired
    private AuthenticationFailureHandlerImpl authenticationFailureHandler;
    @Autowired
    private AuthenticationSuccessHandlerImpl authenticationSuccessHandler;
    @Autowired
    private SysUserSelfSupportService sysUserSelfSupportService;
    @Autowired
    private LogoutHandlerImpl logoutHandlerImpl;
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private ResponseHeadersProperties responseHeadersProperties;
    @Autowired
    private UserTokenProperties userTokenProperties;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //使用自定义权限认证失败处理 - 不使用重定向
        http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);
        // 由于使用的是JWT，我们这里不需要csrf , 并且关闭缓存
        http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //放开以下链接
        http.authorizeRequests().antMatchers("/api/**","/admin/common/**").permitAll();
        http.authorizeRequests().antMatchers(HttpMethod.PATCH,"/admin/security/self").permitAll();
        if (!StringUtils.isEmpty(userTokenProperties.getPermitUri())) {
            http.authorizeRequests().antMatchers(userTokenProperties.getPermitUri().split(",")).permitAll();
        }
        //下列链接登录后即可访问
        http.authorizeRequests().antMatchers("/admin/security/self/**").authenticated();
        if (!StringUtils.isEmpty(userTokenProperties.getAuthenticatedUrl())) {
            http.authorizeRequests().antMatchers(userTokenProperties.getAuthenticatedUrl().split(",")).authenticated();
        }
        // 配置自定义登录退出
        http.formLogin()
                .loginPage(userTokenProperties.getAuthWebLoginPath()).successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).permitAll()
                .and().
                logout().logoutUrl(userTokenProperties.getAuthWebLogoutPath()).addLogoutHandler(logoutHandlerImpl).logoutSuccessHandler(logoutSuccessHandler).permitAll();
        //开启自定义连接拦截
        http.authorizeRequests().anyRequest().access("@rbacAuthorityService.hasPermission(request,authentication)");
        http.rememberMe().rememberMeParameter("remember-me").tokenValiditySeconds(responseHeadersProperties.getMaxAge());
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        // 禁用缓存
        http.headers().cacheControl();

        JwtTokenUtils.EXPIRES = responseHeadersProperties.getExpires();
        JwtTokenUtils.SECRET = userTokenProperties.getSecret();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(daoAuthenticationProvider());
//        auth.userDetailsService(sysUserCmsServiceImpl).passwordEncoder(new BCryptPasswordEncoder());
    }


    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setHideUserNotFoundExceptions(false);
        provider.setUserDetailsService(sysUserSelfSupportService);
        provider.setPasswordEncoder(new BCryptPasswordEncoder());
        return provider;
    }
}
